﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.DynamicData;

namespace Data.LINQ {

	#region MotoBank

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Moto bank. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class MotoBank : MotoBankDataContext {
		public static System.Web.DynamicData.MetaModel MetaModel = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the database. </summary>
		///
		/// <value>	The database. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MotoBank DB { get { return new MotoBank(); } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Static constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		static MotoBank() {
			MetaModel = new System.Web.DynamicData.MetaModel();
			MetaModel.RegisterContext(typeof(MotoBank));
			var check = MetaModel.Tables.Select(
				t => t.Columns
					.Where(c=>c as MetaForeignKeyColumn == null)
					.Select(
						c => c.Attributes.OfType<EditColumnTemplateAttribute>()
							.Select(a => a.LookUpFieldName + a.LookUpTextField + a.LookUpValueField)
							.ToArray()
					).ToArray()
			).Count();
			var noKey = MetaModel.Tables.Where(t => t.Attributes.OfType<SelectTableAttribute>().Count() > 0)
				.FirstOrDefault(t => t.Columns.Where(c => c.IsPrimaryKey || c.Attributes.OfType<ClientKeyAttribute>().Count() > 0).Count() == 0);
			if (noKey != null) throw new Exception("Entity " + noKey.Name + " has SelectTable attribute without any keys.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Default constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public MotoBank()
			: base(
				new Dimok.User.UserObject().db
				) {
					CommandTimeout = 60 * 5;
		}

		#region Experiments

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Selects. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <typeparam name="TEntity">	Type of the entity. </typeparam>
		/// <param name="Keys">	A variable-length parameters list containing keys. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Obsolete("Use TableExtensions.SelectByKey extention metod", true)]
		public IQueryable<TEntity> Select<TEntity>(params object[] Keys) where TEntity : class {
			var table = GetTable<TEntity>();
			var mapping = Mapping.GetTable(typeof(TEntity));
			var keys = mapping.RowType.DataMembers.Where(s => s.IsPrimaryKey == true);
			List<System.Data.Linq.Mapping.MetaDataMember> lstKeys = new List<System.Data.Linq.Mapping.MetaDataMember>();
			Func<TEntity, bool> predicate = delegate(TEntity t) {
				int i = 0;
				foreach (System.Data.Linq.Mapping.MetaDataMember key in keys) {
					var memberID = t.GetType().GetProperty(key.Name).GetValue(t, null);
					if (memberID.GetHashCode() != Keys[i++].GetHashCode()) return false;
				}
				return true;
			};
			return table.Where(predicate).AsQueryable<TEntity>();
			//return  Context.GetTable<TEntity>().Where(s => s.LoanID == LoanID && s.SnapshotName == SnapshotName);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Update an Existing Object. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <typeparam name="T">	. </typeparam>
		/// <param name="item">	The object to update. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void Update<T>(T item) where T : class {
			try {
				// create a new instance of the object
				Object newObj = Activator.CreateInstance(typeof(T), new object[0]);
				PropertyDescriptorCollection originalProps = TypeDescriptor.GetProperties(item);
				// set the new object to match the passed in object
				foreach (PropertyDescriptor currentProp in originalProps) {
					if (currentProp.Attributes[typeof(System.Data.Linq.Mapping.ColumnAttribute)] != null) {
						object val = currentProp.GetValue(item);
						currentProp.SetValue(newObj, val);
					}
				}
				// attach the new object to a new data context and
				// call submit changes on the context
				var table = GetTable<T>();
				table.Attach((T)newObj, true);
				SubmitChanges();
			} catch (Exception) { throw; }

		}
		#endregion

	}
	#endregion

}